package org.jetlinks.pro.datasource.rdb;

import org.hswebframework.web.bean.FastBeanCopier;
import org.jetlinks.pro.datasource.DataSource;
import org.jetlinks.pro.datasource.DataSourceConfig;
import org.jetlinks.pro.datasource.DataSourceProvider;
import org.jetlinks.pro.datasource.DataSourceType;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import javax.annotation.Nonnull;

@Component
public class RDBDataSourceProvider implements DataSourceProvider {

    @Nonnull
    @Override
    public DataSourceType getType() {
        return RDBDataSourceType.rdb;
    }

    @Nonnull
    @Override
    public Mono<DataSource> createDataSource(@Nonnull DataSourceConfig properties) {

        return Mono
            .<DataSource>fromCallable(() -> RDBDataSourceProvider
                .create(properties.getId(),
                        FastBeanCopier.copy(properties.getConfiguration(), new RDBDataSourceProperties())
                                      .validate()
                )
            )
            .subscribeOn(Schedulers.boundedElastic());
    }

    @Nonnull
    @Override
    public Mono<DataSource> reload(@Nonnull DataSource dataSource, @Nonnull DataSourceConfig properties) {
        return Mono
            .defer(() -> {
                RDBDataSourceProperties dataSourceProperties = FastBeanCopier
                    .copy(properties.getConfiguration(), RDBDataSourceProperties::new)
                    .validate();
                if (dataSource.isWrapperFor(DefaultRDBDataSource.class)) {
                    dataSource
                        .unwrap(DefaultRDBDataSource.class)
                        .setConfig(dataSourceProperties);
                    return Mono.just(dataSource);
                }
                dataSource.dispose();
                return createDataSource(properties);
            })
            .subscribeOn(Schedulers.boundedElastic());
    }

    public static RDBDataSource create(String id, RDBDataSourceProperties properties) {
        return new DefaultRDBDataSource(id, properties);
    }
}
